﻿namespace Z2
{

	using Microsoft.Xna.Framework;
	using Microsoft.Xna.Framework.Graphics;
	using Microsoft.Xna.Framework.Input;
	using Z2.Language;
	using Z2.Core;
	using System.Diagnostics;
	using System;
	using System.Collections.Generic;
	using System.Threading;
	using Microsoft.Xna.Framework.GamerServices;

	/// <summary>
	/// This is the main type for your game
	/// </summary>
	public class Zelvici2 : Game
	{

		#region Members

		private RenderTarget2D m_lightBuffer;
		private Rectangle m_screen;

		private GraphicsDeviceManager m_graphics;
		private SpriteBatch m_spriteBatch;

		private GameCursor m_cursor;
		private Player m_player;
		private Camera m_camera;
		private Hud m_hud;
		private World m_world;
		private KeyboardControl m_control;

		private string m_runMap;

		
		private bool m_paused;

		#endregion

		#region Constructor

		/// <summary>
		/// Konstruktor
		/// </summary>
		/// <param name="runMap">Pokud obsahuje název mapy, spustí se tato mapa.</param>
		public Zelvici2(string runMap)
			: base()
		{
			this.m_runMap = runMap;

			this.m_graphics = new GraphicsDeviceManager(this);
			this.m_graphics.PreferredBackBufferWidth = Properties.Settings.Default.Width;
			this.m_graphics.PreferredBackBufferHeight = Properties.Settings.Default.Height;
			this.m_graphics.IsFullScreen = Properties.Settings.Default.Fullscreen;
			this.m_graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(this.Graphics_PreparingDeviceSettings);
			Zelvici2.Graphics = this.m_graphics;
			
		}

		#endregion

		internal static GraphicsDeviceManager Graphics { get; private set; }

		public void Pause()
		{
			this.m_paused = !this.m_paused;
		}

		public ResolveTexture2D GetScreenshot()
		{
			ResolveTexture2D screenshot = new ResolveTexture2D(
				this.m_graphics.GraphicsDevice,
				this.m_graphics.GraphicsDevice.PresentationParameters.BackBufferWidth,
				this.m_graphics.GraphicsDevice.PresentationParameters.BackBufferHeight, 1,
				this.m_graphics.GraphicsDevice.PresentationParameters.BackBufferFormat);
			screenshot.GraphicsDevice.ResolveBackBuffer(screenshot);
			this.m_spriteBatch.Begin();
			this.m_spriteBatch.Draw(screenshot, Vector2.Zero, Color.White);
			this.m_spriteBatch.End();
			return screenshot;
		}

		#region Override Methods

		protected override void Initialize()
		{
			this.Window.Title = Strings.WindowTitle;
			
			SpriteManager.Instance.Initialize(this.Content, this.m_graphics);
			SoundManager.Instance.Initialize(this.Content);

			this.m_camera = new Camera(this.m_graphics);
			this.m_lightBuffer = new RenderTarget2D(this.GraphicsDevice,
				this.m_graphics.PreferredBackBufferWidth,
				this.m_graphics.PreferredBackBufferHeight, 1,
				SurfaceFormat.Color);
			this.m_screen = new Rectangle(0, 0, this.m_graphics.PreferredBackBufferWidth, this.m_graphics.PreferredBackBufferHeight);
			//this.m_screen.Inflate(-100, -100);
			this.m_control = new KeyboardControl();
			this.m_control.KeyPressed += new EventHandler<KeyEventArgs>(this.KeyPressed);

			base.Initialize();

		}

		private void KeyPressed(object sender, KeyEventArgs e)
		{
			if (e.Key == Keys.Pause) this.Pause();
			if (e.Key == Keys.L) World.Current.TurnLight(0.01F, 1F);
			if (e.Key == Keys.K) World.Current.TurnLight(0.01F, 0F);
		}

		protected override void LoadContent()
		{
			this.m_spriteBatch = new SpriteBatch(this.GraphicsDevice);

			effect = new BlurEffect(Content, Graphics);
			this.m_cursor = new GameCursor();
			this.m_player = new Player();
			
			this.m_world = new World(string.IsNullOrEmpty(this.m_runMap)? "demo" : this.m_runMap);
			this.m_world.Load();

			this.m_world.RegisterObject(this.m_player);
			this.m_camera.Follow = this.m_player;
			this.m_hud = new Hud(this.m_graphics);
		}
		

		protected override void UnloadContent()
		{
			this.Content.Unload();
			SpriteManager.Instance.Dispose();
			base.UnloadContent();
		}

		protected override void Update(GameTime gameTime)
		{
			this.m_control.Update();
			this.m_cursor.Update();

			MouseState state = Mouse.GetState();
			if (state.LeftButton == ButtonState.Pressed)
			{
				ParticleEngine.Instance.Create(
					new Vector2(
						state.X - Camera.Instance.Position.X,
						state.Y - Camera.Instance.Position.Y
						), ParticleSettings.Default);
			}

			if(this.m_paused) return;
			
			this.m_hud.Update();
			this.m_world.Update();
			this.m_player.Update();
			
			base.Update(gameTime);
		}


		private void BeginDrawLight()
		{
			if (World.Current.GlobalLight == 1.0F) return;
			this.GraphicsDevice.SetRenderTarget(0, this.m_lightBuffer);
			this.GraphicsDevice.Clear(World.Current.GlobalColorLight);
			this.m_spriteBatch.Begin(SpriteBlendMode.Additive, SpriteSortMode.Immediate, SaveStateMode.None);
			this.m_world.DrawLight(this.m_spriteBatch);
			this.m_spriteBatch.End();
			this.GraphicsDevice.SetRenderTarget(0, null);
		}

		private BlurEffect effect;
		private void EndDrawLight()
		{
			if (World.Current.GlobalLight == 1.0F) return;
			this.m_spriteBatch.Begin(SpriteBlendMode.Additive, SpriteSortMode.Immediate, SaveStateMode.None);
			this.GraphicsDevice.RenderState.SourceBlend = Blend.Zero;
			this.GraphicsDevice.RenderState.DestinationBlend = Blend.SourceColor;

			this.m_spriteBatch.Draw(this.m_lightBuffer.GetTexture(), this.m_screen, Color.White);
			
			this.m_spriteBatch.End();
		}
		
		protected override void Draw(GameTime gameTime)
		{
            //this.SuppressDraw();
			this.BeginDrawLight();
			this.m_spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.FrontToBack, SaveStateMode.SaveState);
			this.m_world.Draw(this.m_spriteBatch);
			this.m_spriteBatch.End();
			this.EndDrawLight();
			//effect.Draw(null, this.m_spriteBatch, gameTime);
			
			this.m_world.DrawWater(this.m_spriteBatch, gameTime);

			this.m_spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState);
			this.m_hud.Draw(this.m_spriteBatch);
			this.m_cursor.Draw(this.m_spriteBatch);
			
			if (this.m_paused)
			{
				this.m_spriteBatch.DrawString(SpriteManager.Instance.GenericFont, "Paused", new Vector2((this.m_screen.Width/2)-20, (this.m_screen.Height/2)-5) , Color.White);
			}

			this.m_spriteBatch.End();
			
			base.Draw(gameTime);
		}

		#endregion

		#region Event Handling

		void Graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
		{
			PresentationParameters pp = e.GraphicsDeviceInformation.PresentationParameters;
#if XBOX
			pp.MultiSampleQuality = 0;
			pp.MultiSampleType = MultiSampleType.FourSamples;
#else
			// TODO: Načíst nastavení
#endif
		}

		#endregion

	}
}
